/**
 * @file Frequency_Scrambling.h
 * @author Bernhard Schildendorfer
 */


#ifndef FREQUENCY_SCRAMBLING_H_
#define FREQUENCY_SCRAMBLING_H_

#include "crypto_engine.h"

/**
 * @brief Encrypts and decrypts audio samples using the Frequency Permutation algorithm.
 *
 * @author Bernhard Schildendorfer
 *
 * The audio signal is transformed into its frequency components which are afterwards
 * randomly permuted using a cryptographic key. The member variable mSamplesNeeded is
 * very important, because it tells the cryptoEngine how many samples it has to deliver
 * to the encryption and decryption method.
 */

class CFrequencyScrambling: public CCryptoEngine {



public:

	CFrequencyScrambling(NAudioFormats::SStreamInfo ioStreamInfo);

	virtual ~CFrequencyScrambling();

	/**
	 * Encrypts pCount bytes from data and write them back. pCount should
	 * never be too less data for encryption because mSamplesNeeded
	 * tells the cryptoEngine to buffer that amount of data for this method
	 *
	 * @param data double array with amplitude values from -1.0 to 1.0
	 * @param pCount  count of audio samples to work with
	 * @return 0 for success, >0 for success and discard of samples for next
	 *         call, <0 for a<n error
	 */

	virtual int encrypt(double *pData, unsigned int pCount);

	/**
	 * Decrypts pCount bytes from data and write them back. pCount should
	 * never be too little data for encryption because mSamplesNeeded
	 * tells the cryptoEngine to buffer that amount of data for this method
	 *
	 * @param data double array with amplitude values from -1.0 to 1.0
	 * @param pCount count of audio samples to work with
	 * @return 0 for success, >0 for success and discard of samples for next
	 *         call, <0 for an error
	 */
	virtual int decrypt(double *pData, unsigned int pCount);



protected:
	/**
	 * called by the protocol engine upon settings change
	 * (e.g. change of embedding parameters)
	 * calls setProperties and initCrypto
	 * if this method gets overwritten, the subclass should call
	 * setProperties and initCrypto
	 */
	virtual int changeSettings();

	/**
	 * Indicates the amount of Samples which are needed for encryption
	 * and decryption. This amount of samples will be buffered in
	 * cryptoEngine. Exactly that many samples will be passed to the
	 * encrypt() and decrypt() method. If the sub-class want's a
	 * different size of samples it can override this method and return
	 * the wanted size.Per default the FFT Framesize will be returned.
	 *
	 * @return sample count which are needed for encryption and decryption
	 */
	virtual unsigned int getSamplesNeeded();

	/**
	 * Calculates the permutation vector needed for both encryption and
	 * decryption. The vector contains a unique numbers of 0 to pCount
	 * in Random order.
	 *
	 * @param pVector integer array of size pCount where the permutation
	 *                vector should be stored
	 * @param pCount size of pVector
	 * @param pAlgorithm Used algorithm for the calculation. The algorithm
	 *                   can have the values of the static variables
	 *                   sPERMUTATION_*
	 * @param pMin Indexes below this one are not permuted
	 * @param pMax Indexes above this one are not permuted
	 */
	unsigned int getPermutationVector(unsigned int *pVector, unsigned int pCount,
			       unsigned int pAlgorithm, unsigned int pMin, unsigned int pMax);

private:
	/**
	 * Called by either encrypt() or decrypt(). Because both of these methods
	 * do nearly the same, they are summarized in dencrypt().
	 *
	 * @param data double array with amplitude values from 0 to 1
	 * @param pCount count of audio samples to work with
	 * @param bEncrypt Indicates weither it should be encrypted or decrypted.
	 *                 true=encryption, false=decryption
	 * @return depends on bEncrypt, see encrypt() and decrypt()
	 */
	int dencrypt(double * pData, unsigned int pCount, bool bEncrypt);

	static const std::string sIniSectionName;
	static const int sPERMUTATION_NULL = 0;   //!< Permutation has no effect. Only for testing
	static const int sPERMUTATION_REVERSE = 1;   //!< Frequencies become inversed
	static const int sPERMUTATION_SWAPPING_AES = 2;      //!< AES is used for the permutation
	static const int sPERMUTATION_SWAPPING_AES_BLOCKED = 3;   //!< Like SWAPPING_AES but it is done in blocks
	static const int sENCRYPTION_MODE_FFT=1;   //!< FFT will be used, for future use
	unsigned int mPermutationMode;   //!< The used permutatino mode like SWAPPING_AES
	unsigned int mEncryptionMode;   //!< The used encryption mode like FFT
	unsigned int mSamplesNeeded;   //!< Defines how many Samples are needed at en-/decryption
};

#endif /* FREQUENCY_SCRAMBLING_H_ */
